/**
 * 
 */
package Parser;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import Crawler.Structure.RegexExpressions;
import Crawler.Structure.RegexExpressions.Expression;
import Structure.MeaningWordPair;
import Structure.Translation;
import Structure.Word;

/**
 * @author Tony
 * 
 */
public class ENChapterParser implements IChapterInterpreter {

	public LinkedList<Word> words = new LinkedList<Word>();

	// for short names to names
	private final HashMap<String, String> langCodes;

	// for words
	private String languageOfContent;

	// pattern
	private final RegexExpressions expr = new RegexExpressions();
	/**
	 * pattern to match the origin language in the not xml text
	 */
	
	private Pattern pTranslations = Pattern.compile("=====Translation.*=====");


	/**
	 * 1 language 2 rest "{{en}}:......."
	 */
	private Pattern pBeginTranslation;

	public ENChapterParser(String propertiesFile) {

		this.expr.loadFromProperties(propertiesFile);
		this.langCodes = new HashMap<String, String>();

		// read langCodes from File and write them into the Map
		try {
			BufferedReader bf = new BufferedReader(new FileReader(
					"properties/deLangCodes.txt"));
			String tmp;
			while ((tmp = bf.readLine()) != null) {
				String[] splits = tmp.split(";");
				langCodes.put(splits[0], splits[1]);
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();

		}

		// load the other regex from properties file
		Properties p = new Properties();
		try {
			BufferedReader bf = new BufferedReader(new FileReader(
					propertiesFile));
			p.load(bf);

			languageOfContent = p.getProperty("languageOfContent");
		

			pBeginTranslation = Pattern.compile(p
					.getProperty("pBeginTranslation"));

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();

		}
	}

	@Override
	public List<Word> parseChapters(String word, List<Chapter> listChapter) {

		LinkedList<Word> listWords = new LinkedList<>();

		// int currentLevel = -1;

		String currentLanguage = null;
		Word currentWord = null;

		for (Chapter chapter : listChapter) {

			if (chapter.depth == 1) {
				currentLanguage = chapter.name.replace("=", "");
			}
			// else if(chapter.depth==2){
			// Matcher m = pEtymology.matcher(chapter.name);
			// if(m.matches()){
			//
			// }
			// }
			else if (chapter.depth == 3) {
				//add the old to list
				if (currentWord != null) {
					listWords.add(currentWord);
				}
				
				currentWord = new Word(word, currentLanguage, languageOfContent);
			} else if (chapter.depth == 4) {
				Matcher m = pTranslations.matcher(chapter.name);
				if (m.matches()) {
					if (currentWord != null)
						currentWord.translations = parseTranslationFromChapter(chapter.content);
					else
						System.out.println("no current word set: " + word);
				}
			}

		}

		Iterator<Word> it = listWords.iterator();
		while(it.hasNext()){
			Word w=it.next();
			if(w.translations.length==0)
				it.remove();
		}
				
		
		return listWords;
	}

	private Translation[] parseTranslationFromChapter(String chapterContent) {
		String[] lines = chapterContent.split("\n");

		String regexNotCheckedTranslation= "\\{\\{checktrans-top\\}\\}";
		
		// contains the translation for the different languages
		HashMap<String, Translation> language = new HashMap<String, Translation>();

		for (String line : lines) {
			if(line.matches(regexNotCheckedTranslation))
				break;
			
			// translation line
			Matcher m = pBeginTranslation.matcher(line);
			if (m.matches()) {
				String langWord=m.group(1).replaceAll("\\]|\\[", "");
				// add new translation language if not exists
				if (!language.containsKey(langWord)) {
					language.put(langWord, new Translation(langWord,
							new LinkedList<MeaningWordPair>()));
					
				}
				// open translation
				Translation t = language.get(langWord);

				// initialize information for analysis
				String part = m.group(2);

				// parses the rest of the line and add the information
				// to the translation t
				parseTranslationLine(t, part);
			}
		}

		// transform translations
		Set<String> keys = language.keySet();
		Iterator<String> it = keys.iterator();

		LinkedList<Translation> listTranslation = new LinkedList<Translation>();

		while (it.hasNext()) {
			Translation t = language.get(it.next());

			// copy only the translation where at least one translation word
			// exists
			if (t.meaningWordMap.size() > 0)
				listTranslation.add(t);

		}

		return listTranslation.toArray(new Translation[0]);
	}

	/**
	 * parses a line with the information about the translation of a word.
	 * 
	 * @param t
	 * @param meaning
	 * @param line
	 */
	public void parseTranslationLine(Translation t, String line) {
		int meaning = 1;
		String part = line;

		boolean match = true;
		int type = -1;
		while (match) {
			match = false;

			// first run
			if (type == -1) {
				for (int i = 0; i < expr.expressions.size() && match == false; i++) {
					Iterator<Expression> it = expr.expressions.get(i).samePattern
							.iterator();
					// test all types of translation formats/matcher
					while (it.hasNext() && match == false) {
						Expression e = it.next();
						Matcher mTN = e.pattern.matcher(part);

						if (mTN.matches()) {
							// parse meanings

							// add translations for meanings

							t.meaningWordMap.add(new MeaningWordPair(1, mTN
									.group(e.word)));
							
							part = mTN.group(e.rest);
							match = true;
							type = i;
						}
					}
				}

			} else {

				// same part
				Iterator<Expression> it = expr.expressions.get(type).samePattern
						.iterator();
				while (it.hasNext() && match == false) {
					Expression e = it.next();
					Matcher mT1S = e.pattern.matcher(part);
					if (mT1S.matches()) {

						// add translations for meanings

						t.meaningWordMap.add(new MeaningWordPair(meaning, mT1S
								.group(e.word)));

						part = mT1S.group(e.rest);
						match = true;
					}
				}

			}
		}
	}


}
